{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"red\">注</font>: 使用 tensorboard 可视化需要安装 tensorflow (TensorBoard依赖于tensorflow库，可以任意安装tensorflow的gpu/cpu版本)\n",
    "\n",
    "```shell\n",
    "pip install tensorflow-cpu\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:12.920359Z",
     "start_time": "2025-01-20T02:59:12.916797Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.0\n",
      "torch 2.5.1+cpu\n",
      "cpu\n"
     ]
    }
   ],
   "execution_count": 19
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据准备"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:12.993323Z",
     "start_time": "2025-01-20T02:59:12.960551Z"
    }
   },
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torch.utils.data import random_split\n",
    "\n",
    "# fashion_mnist图像分类数据集\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 这里用 random_split 按照 11 : 1 的比例来划分数据集\n",
    "train_ds, val_ds = random_split(train_ds, [55000, 5000], torch.Generator().manual_seed(seed))"
   ],
   "outputs": [],
   "execution_count": 20
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:12.996613Z",
     "start_time": "2025-01-20T02:59:12.993839Z"
    }
   },
   "source": [
    "from torchvision.transforms import Normalize\n",
    "\n",
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img.mean(dim=(1, 2))\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "# print(cal_mean_std(train_ds))\n",
    "# 0.2860， 0.3205\n",
    "transforms = nn.Sequential(\n",
    "    Normalize([0.2856], [0.3202])\n",
    ")"
   ],
   "outputs": [],
   "execution_count": 21
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:13.004725Z",
     "start_time": "2025-01-20T02:59:12.996613Z"
    }
   },
   "source": [
    "from torch.utils.data.dataloader import DataLoader\n",
    "\n",
    "batch_size = 32\n",
    "# 从数据集到dataloader\n",
    "train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)\n",
    "val_loader = DataLoader(val_ds, batch_size=batch_size, shuffle=False, num_workers=4)\n",
    "test_loader = DataLoader(test_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
   ],
   "outputs": [],
   "execution_count": 22
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型\n",
    "\n",
    "使用深度可分离的卷积\n",
    "\n",
    "pytorch需要自行实现"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 深度可分离卷积其实就是先对输入的通道进行卷积，然后再进行1x1的卷积，这样可以减少参数量，提高效率。"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 一定要有groups参数，groups参数表示一个卷积核的每个通道分别进行运算。在depthwise_conv2d中，输入的通道数等于输出的通道数，groups等于输入的通道数。"
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:13.008225Z",
     "start_time": "2025-01-20T02:59:13.005400Z"
    }
   },
   "source": [
    "# 定义深度可分离卷积层，torch没有实现，tf有实现\n",
    "class DepthWiseConv2d(nn.Module):\n",
    "    def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, bias=True):\n",
    "        super(DepthWiseConv2d, self).__init__() #这里写为super().__init__()，等价的\n",
    "        self.depthwise_conv = nn.Conv2d(in_channels, in_channels, kernel_size, stride, padding, groups=in_channels, bias=False) #groups参数表示一个卷积核的每个通道分别进行运算\n",
    "        self.pointwise_conv = nn.Conv2d(in_channels, out_channels, 1, 1, 0, bias=bias)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.depthwise_conv(x)\n",
    "        x = self.pointwise_conv(x)\n",
    "        return x"
   ],
   "outputs": [],
   "execution_count": 23
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# enumerate(...)：对 named_parameters() 的结果进行枚举，返回一个包含索引 idx 和 (key, value) 元组的迭代器。"
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:13.015670Z",
     "start_time": "2025-01-20T02:59:13.008225Z"
    }
   },
   "source": [
    "\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self, activation=\"relu\"):\n",
    "        super(CNN, self).__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=\"same\")\n",
    "        self.conv2 = DepthWiseConv2d(in_channels=32, out_channels=32, kernel_size=3, padding=\"same\")\n",
    "        self.pool = nn.MaxPool2d(2, 2)\n",
    "        self.conv3 = DepthWiseConv2d(in_channels=32, out_channels=64, kernel_size=3, padding=\"same\")\n",
    "        self.conv4 = DepthWiseConv2d(in_channels=64, out_channels=64, kernel_size=3, padding=\"same\")\n",
    "        self.conv5 = DepthWiseConv2d(in_channels=64, out_channels=128, kernel_size=3, padding=\"same\")\n",
    "        self.conv6 = DepthWiseConv2d(in_channels=128, out_channels=128, kernel_size=3, padding=\"same\")\n",
    "        self.flatten = nn.Flatten()\n",
    "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
    "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
    "        self.fc2 = nn.Linear(128, 10)\n",
    "        \n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                if m.bias is not None:\n",
    "                    nn.init.zeros_(m.bias)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        #x -->(batch_size, 1, 28, 28)\n",
    "        x = self.pool(act(self.conv2(act(self.conv1(x)))))  # (batch_size, 32, 14, 14)\n",
    "        x = self.pool(act(self.conv4(act(self.conv3(x)))))  # (batch_size, 64, 7, 7)\n",
    "        x = self.pool(act(self.conv6(act(self.conv5(x)))))  # (batch_size, 128, 3, 3)\n",
    "        x = self.flatten(x) # (batch_size, 128 * 3 * 3)\n",
    "        x = act(self.fc1(x)) # (batch_size, 128)\n",
    "        x = self.fc2(x) # (batch_size, 10)\n",
    "        return x\n",
    "    \n",
    "\n",
    "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
    "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\")\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight\tparamerters num: 288\n",
      "conv1.bias\tparamerters num: 32\n",
      "conv2.depthwise_conv.weight\tparamerters num: 288\n",
      "conv2.pointwise_conv.weight\tparamerters num: 1024\n",
      "conv2.pointwise_conv.bias\tparamerters num: 32\n",
      "conv3.depthwise_conv.weight\tparamerters num: 288\n",
      "conv3.pointwise_conv.weight\tparamerters num: 2048\n",
      "conv3.pointwise_conv.bias\tparamerters num: 64\n",
      "conv4.depthwise_conv.weight\tparamerters num: 576\n",
      "conv4.pointwise_conv.weight\tparamerters num: 4096\n",
      "conv4.pointwise_conv.bias\tparamerters num: 64\n",
      "conv5.depthwise_conv.weight\tparamerters num: 576\n",
      "conv5.pointwise_conv.weight\tparamerters num: 8192\n",
      "conv5.pointwise_conv.bias\tparamerters num: 128\n",
      "conv6.depthwise_conv.weight\tparamerters num: 1152\n",
      "conv6.pointwise_conv.weight\tparamerters num: 16384\n",
      "conv6.pointwise_conv.bias\tparamerters num: 128\n",
      "fc1.weight\tparamerters num: 147456\n",
      "fc1.bias\tparamerters num: 128\n",
      "fc2.weight\tparamerters num: 1280\n",
      "fc2.bias\tparamerters num: 10\n"
     ]
    }
   ],
   "execution_count": 24
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 第一次是Cin/*k/*k,第二次是Cin/*Cout/*1/*1"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:13.020796Z",
     "start_time": "2025-01-20T02:59:13.015670Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def count_parameters(model): #计算模型总参数量\n",
    "    return sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
    "count_parameters(CNN())"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "184234"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 25
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:13.024304Z",
     "start_time": "2025-01-20T02:59:13.020796Z"
    }
   },
   "cell_type": "code",
   "source": "288 + 288 +288+ 1024 + 2048 + 576 +576+ 4096+ 8192 + 1152 + 16384 + 147456 + 1280",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "183648"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 26
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:13.027128Z",
     "start_time": "2025-01-20T02:59:13.024304Z"
    }
   },
   "cell_type": "code",
   "source": "32 + 32 + 64 + 64 + 128 + 128 +128+ 10",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "586"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 27
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:13.030245Z",
     "start_time": "2025-01-20T02:59:13.027128Z"
    }
   },
   "cell_type": "code",
   "source": "183648+586",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "184234"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 28
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:13.068570Z",
     "start_time": "2025-01-20T02:59:13.031251Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 29
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:15.572230Z",
     "start_time": "2025-01-20T02:59:13.068570Z"
    }
   },
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "outputs": [],
   "execution_count": 30
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:15.577093Z",
     "start_time": "2025-01-20T02:59:15.572230Z"
    }
   },
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 31
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T02:59:15.588025Z",
     "start_time": "2025-01-20T02:59:15.578101Z"
    }
   },
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "outputs": [],
   "execution_count": 32
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T03:13:37.766652Z",
     "start_time": "2025-01-20T02:59:24.671879Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                    \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20\n",
    "\n",
    "activation = \"selu\"\n",
    "model = CNN(activation)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用SGD\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(f\"runs/dsc-{activation}\")\n",
    "tensorboard_callback.draw_model(model, [1, 1, 28, 28])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(f\"checkpoints/dsc-{activation}\", save_step=len(train_loader), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=10)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_loader)\n",
    "    )"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/34380 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "0f4b0cf5df344bb8a27fecef1af917e0"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 33
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T04:24:45.817469Z",
     "start_time": "2025-01-20T04:24:45.607036Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=500)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 34
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T04:25:07.157526Z",
     "start_time": "2025-01-20T04:25:02.817773Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(f\"checkpoints/dsc-{activation}/best.ckpt\", weights_only=True,map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, test_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.3665\n",
      "accuracy: 0.8682\n"
     ]
    }
   ],
   "execution_count": 36
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
